#include "metapso.h"
#include "pso.h"
#include "params.h"
#include <iomanip>


//------------------------------------------------------------------------------
// Public Functions

MetaPso::MetaPso()
{
    
}

void MetaPso::testAlphas()
{
    double alpha_1_range[] = {-2.0,2.01};
    double alpha_2_range[] = {-2.0,2.01};
    const double alpha_step = 0.1;
    // The alphas to test.
    double a1, a2;
    // Test to do for each alpha set.
    const unsigned int pso_tests = 5;
    // The obtained results.
    double solutions;
    // Create a pso that does not log events.
    Params params;
    Pso pso(&params, false);

    // Open a log file.
    m_logs.open("alphas.plot");
    
    // Test the PSO algorithm with varying sets of alphas.
    for(a1 = alpha_1_range[0]; a1 <= alpha_1_range[1]; a1 += alpha_step) {
        for(a2 = alpha_2_range[0]; a2 <= alpha_2_range[1]; a2 += alpha_step) {
            
            solutions = 0;
            for(unsigned int i = 0; i < pso_tests; ++i) {
                solutions += pso.exec(a1, a2);
            }

            m_logs.log("alphas.plot")
                << std::setw(16)
                << a1
                << std::setw(16)
                << a2
                << std::setw(16)
                << (solutions/pso_tests)
                << std::endl;
        }
        // Add line between each change of alpha_1.
        m_logs.log("alphas.plot")
            << std::endl;
    }

    // Close the logs.
    m_logs.close();
}

void MetaPso::testOmega()
{
    // Create a pso that does not log events.
    Params params;
    Pso pso(&params, false);
    // Test to do for each omega set.
    const unsigned int pso_tests = 10;
    double omega_range[] = {0.729,0.1};
    const double omega_step = 0.01;
    double omega_bottom;
    double solution;

    // Open a log file.
    m_logs.open("omegas.plot");

    for(omega_bottom = omega_range[0]; omega_bottom >= omega_range[1]; omega_bottom -= omega_step) {

        solution = 0.0;
        for(unsigned int i = 0; i < pso_tests; ++i) {
            solution += pso.execOmega(omega_range[0], omega_bottom);
        }

        m_logs.log("omegas.plot")
            << std::setw(16)
            << omega_range[0]
            << std::setw(16)
            << omega_bottom
            << std::setw(16)
            << (solution/pso_tests)
            << std::endl;
    }

    // Close the logs.
    m_logs.close();
}

void MetaPso::metaPso()
{
    double solution;
    // Some params.
    Params params;
    params.swarm_size = 30;
    params.neighbours = 30;
    params.iterations = 100;
    params.dimensions = 6;
    params.alpha_1 = 1.494;
    params.alpha_2 = 1.494;
    params.alpha_3 = 0;
    params.omega_top = 0.729;
    params.omega_bottom = 0.1;
    params.boundary_radius = 5;
    params.fitness_function = 4; // The fitness is another PSO!
    // PSO of PSOs will log!
    Pso pso(&params, true);

    solution = pso.exec();
}


//------------------------------------------------------------------------------
// Private Functions
